package com.bjtang.book.controller.interceptor;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import com.bjtang.book.dto.ReturnDto;
import com.bjtang.book.myexception.DataCheckException;
import com.bjtang.book.myexception.DataErrorException;
import com.bjtang.book.myexception.DataOperateException;
import com.bjtang.book.util.ReturnUtil;

@ControllerAdvice
public class ExceptionAdvice {
	/**
	 * 拦截捕捉自定义异常 ConstraintViolationException.class
	 * 
	 * @param ex
	 * @return
	 */
	@ResponseBody
	@ExceptionHandler(value = ConstraintViolationException.class)
	public ReturnDto ConstraintViolationExceptionHandler(ConstraintViolationException ex) {
		Set<ConstraintViolation<?>> constraintViolations = ex.getConstraintViolations();
		Iterator<ConstraintViolation<?>> iterator = constraintViolations.iterator();
		List<String> msgList = new ArrayList<>();
		while (iterator.hasNext()) {
			ConstraintViolation<?> cvl = iterator.next();
			msgList.add(cvl.getPropertyPath() + cvl.getMessage());
		}
		return ReturnUtil.error(msgList, 400, "数据出错");
	}

	/**
	 * 用于实体类的数据校验支持
	 **/
	@ResponseBody
	@ExceptionHandler(value = MethodArgumentNotValidException.class)
	public ReturnDto ConstraintViolationExceptionHandler2(MethodArgumentNotValidException ex) {
		BindingResult bindingResult = ex.getBindingResult();
		List<FieldError> fieldErrors = bindingResult.getFieldErrors();
		List<String> msgList = new ArrayList<>();
		fieldErrors.forEach(e -> msgList.add(e.getObjectName() + "." + e.getField() + ":" + e.getDefaultMessage()));
		return ReturnUtil.error(msgList, 400, "数据出错");
	}

	/*
	 * 用于数据异常无法转换的数据校验支持 特别是get方法的String转Long
	 */
//	@ResponseBody
//	@ExceptionHandler(value = java.lang.NumberFormatException.class)
//	public ReturnDto ConstraintViolationExceptionHandler3(NumberFormatException ex) {
//		String message = ex.getMessage();
//		return ReturnUtil.error(message, 400, "数据转换出错");
//	}

	@ResponseBody
	@ExceptionHandler(value = Exception.class)
	public ReturnDto errorHandler(Exception ex) {
		System.err.println(ex.getClass());
		if (ex instanceof MethodArgumentTypeMismatchException) {
			return ReturnUtil.error(ex.getMessage(), 400, "数据转换出错");
		}
		if (ex instanceof DataCheckException) {
			return ReturnUtil.error(ex.getMessage(), 400, "数据检查出错");
		}
		if (ex instanceof DataOperateException) {
			return ReturnUtil.error(ex.getMessage(), 403, "操作失败");
		}
		if (ex instanceof DataErrorException) {
			return ReturnUtil.error(ex.getMessage(), 404, "数据为空");
		}
		if (ex instanceof BadSqlGrammarException) {
			System.err.println(ex.getMessage());
			return ReturnUtil.error("这是一个很严重的错误,或许需要你通知管理员", 500, "sql语句运行出错");
		}
		if (ex instanceof NullPointerException) {
			return ReturnUtil.error(ex.getMessage(), 500, "空值错误");
		}
		if (ex instanceof HttpMessageNotReadableException) {
			return ReturnUtil.error(ex.getMessage(), 500, "json转换错误");
		}
		String message = ex.getMessage();
		return ReturnUtil.error(message, 500, "未知错误");
	}

//	@ExceptionHandler
//	void handleIllegalArgumentException(NumberFormatException e, 
//	                        HttpServletResponse response) throws IOException {    
//	      response.sendError(HttpStatus.BAD_REQUEST.value());
//	}
//	
//	@ExceptionHandler(value ={ IllegalArgumentException.class, NullPointerException.class, NumberFormatException.class,
//			MethodArgumentTypeMismatchException.class })
//	void handleIllegalArgumentException(HttpServletResponse response) throws IOException {
//		response.sendError(HttpStatus.BAD_REQUEST.value());
//	}
}
